#pragma once

namespace hHashVectorDetail
{
	template <typename Val>
	struct Node
	{
		friend struct hHashVector<Val>;
		friend class Iterator<Val, false>;
		friend class Iterator<Val, true>;

		using POwner = hHashVector<Val>*;
		using POwnerPtr = std::shared_ptr<POwner>;
		using PNode = Node*;
		using PPNode = PNode*;
		using PNodePtr = std::shared_ptr<PNode>;
		using Iter = Iterator<Val, false>;
		using CIter = Iterator<Val, true>;

		size_t _key = 0;
		Val* _val = NULL;

		std::pair<size_t, size_t> _idx;
		POwnerPtr _ppOwner;
		PNodePtr _ppParent;
		PNodePtr _ppSelfIt;
		PNodePtr _ppSelfCld;
		PPNode _pChildren = NULL;

		size_t _num = 0;

		Node(POwnerPtr ppOwner);
		Node(Node&& n);
		~Node();

		template<typename... Args>
		Iter emplaceCallback(bool isLst, size_t k, Args... args);
		void eraseCallback();
		Iter findCallback(bool isLst, size_t k);

		auto hashFromKey(size_t k) const->std::pair<size_t, bool>;
		size_t hashToKey(size_t idx) const;

		bool empty() const { return !_num; }
		size_t num() const { return _num; }

		template <typename Func>
		auto show(std::ostream& os, Func func) const->std::ostream&;
#if 0
		size_t calcNum() const;
		size_t calcCapacity() const;
		size_t calcSize() const;
		size_t calcMemNum() const;
		size_t calcMemSize() const;
#endif
	private:
		template<typename... Args>
		Val* addVal(Args... args);
		Iter getIter();
		Iter getNext();
	};
}
